using System.Runtime.CompilerServices;
using System.Threading.Tasks;
#if MYCODE
using BepuUtilities.Vectors;
#else
using System.Numerics;
#endif
namespace Demos.SpecializedTests
{
    public static class CacheBlaster
    {
        const int byteCount = (1 << 24); // 16.7MB比大多数台式机末级缓存都大。如果你在一些GINORMO XEON上运行这个,你会想要选择更高的。
        const int intCount = byteCount / 4;
        static int vectorCount = intCount / Vector<int>.Count;
        static int vectorMask = vectorCount - 1;
        static int[] readblob = new int[intCount];
        static int[] writeblob = new int[intCount];

        /// <summary>
        /// 尝试逐出大部分或所有缓存级别以模拟冷启动。
        /// 对于过大以至于明显超过缓存大小的模拟,不会执行很多操作。
        /// </summary>
        [MethodImpl(MethodImplOptions.NoOptimization)]
        public static void Blast()
        {
            // 我们不能保证处理器使用的是纯LRU更换。一些现代的处理器有点棘手。
            // 扰乱访问应该会使CPU更难缓存数据。
            const int vectorsPerJob = 32;
            int intsPerJob = vectorsPerJob * Vector<int>.Count;
            Parallel.For(0, intCount / intsPerJob, jobIndex =>
            {
                var baseIndex = jobIndex * intsPerJob;
                ref Vector<int> read = ref Unsafe.As<int, Vector<int>>(ref readblob[0]);
                ref Vector<int> write = ref Unsafe.As<int, Vector<int>>(ref writeblob[baseIndex]);

                for (int i = 0; i < vectorsPerJob; ++i)
                {
                    Unsafe.Add(ref write, i) = Unsafe.Add(ref read, (i * 104395303) & vectorMask);
                }
            });
        }
    }
}
